package io.renren.modules.classinfo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.renren.common.exception.RenException;
import io.renren.common.page.PageData;
import io.renren.common.utils.ConvertUtils;
import io.renren.common.service.impl.CrudServiceImpl;
import io.renren.modules.classinfo.dao.StuInfoDao;
import io.renren.modules.classinfo.dto.ClassStuRealationDTO;
import io.renren.modules.classinfo.service.ClassInfoService;
import io.renren.modules.classinfo.service.ClassStuRealationService;
import io.renren.modules.classinfo.vo.ClassInfoVO;
import io.renren.modules.classinfo.vo.ClassStuRealationVO;
import io.renren.modules.classinfo.vo.StuInfoVO;
import io.renren.modules.classinfo.dto.StuInfoDTO;
import io.renren.modules.classinfo.entity.StuInfoEntity;
import io.renren.modules.classinfo.service.StuInfoService;
import io.renren.modules.security.user.SecurityUser;
import io.renren.modules.sys.dto.SysRoleDTO;
import io.renren.modules.sys.dto.SysUserDTO;
import io.renren.modules.sys.service.SysRoleService;
import io.renren.modules.sys.service.SysRoleUserService;
import io.renren.modules.sys.service.SysUserService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 学生信息管理
 *
 * @author test test
 * @since 1.0.0 2024-09-13
 */
@Service
public class StuInfoServiceImpl extends CrudServiceImpl<StuInfoDao, StuInfoEntity, StuInfoVO> implements StuInfoService {

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private SysRoleUserService sysRoleUserService;

    @Autowired
    private ClassInfoService classInfoService;

    @Autowired
    private ClassStuRealationService classStuRealationService;

    @Override
    public QueryWrapper<StuInfoEntity> getWrapper(Map<String, Object> params){
        String id = (String)params.get("id");
        String studentIdList = (String)params.get("studentIdList");

        QueryWrapper<StuInfoEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(id), "id", id);
        if (StringUtils.isNotBlank(studentIdList)) {
            wrapper.in("student_id", studentIdList.split(","));
        }
        wrapper.orderByDesc("testing_score");

        return wrapper;
    }

    @Override
    public void save(StuInfoDTO stuInfoDTO) {
        StuInfoEntity stuInfoEntity = ConvertUtils.sourceToTarget(stuInfoDTO, StuInfoEntity.class);
        this.insert(stuInfoEntity);
    }

    @Override
    public void update(StuInfoDTO stuInfoDTO) {
        StuInfoEntity stuInfoEntity = ConvertUtils.sourceToTarget(stuInfoDTO, StuInfoEntity.class);
        this.updateById(stuInfoEntity);
    }

    @Override
    public PageData<StuInfoVO> stuinfoPage(Map<String, Object> params) {

        Long userId = SecurityUser.getUserId();
        SysRoleDTO studentRole = sysRoleService.getRole("student");
        List<Long> userIdList = sysRoleUserService.getUserIdList(studentRole.getId());
        if (CollectionUtils.isNotEmpty(userIdList) && userIdList.contains(userId)) {
            ClassStuRealationVO classStuRealationVo = classStuRealationService.queryByStudentId(userId);
            if (classStuRealationVo == null) {
                throw new RenException("您还未绑定班级！无法查看班级信息！");
            }
            List<ClassStuRealationVO> classStuRealationVoList = classStuRealationService.queryByClassInfoId(classStuRealationVo.getClassInfoId());
            params.put("studentIdList", classStuRealationVoList.stream().map(e -> e.getStudentId().toString()).distinct().collect(Collectors.joining(",")));
        }

        SysRoleDTO teacherRole = sysRoleService.getRole("teacher");
        List<Long> teacherUserIdList = sysRoleUserService.getUserIdList(teacherRole.getId());
        if (CollectionUtils.isNotEmpty(teacherUserIdList) && teacherUserIdList.contains(userId)) {
            ClassInfoVO classInfoVo = classInfoService.getByTeacherId(userId);
            if (classInfoVo == null) {
                return new PageData<StuInfoVO>(Collections.EMPTY_LIST, 0);
            }
            List<ClassStuRealationVO> classStuRealationVoList = classStuRealationService.queryByClassInfoId(classInfoVo.getId());
            params.put("studentIdList", classStuRealationVoList.stream().map(e -> e.getStudentId().toString()).distinct().collect(Collectors.joining(",")));
        }

        List<StuInfoEntity> entityList = this.baseDao.selectList(getWrapper(params));
        List<StuInfoVO> stuInfoVoList = ConvertUtils.sourceToTarget(entityList, StuInfoVO.class);

        String classInfoId = (String)params.get("classInfoId");
        if (StringUtils.isNotBlank(classInfoId)) {
            List<ClassStuRealationVO> classStuRealationVoList = classStuRealationService.queryByClassInfoId(Long.valueOf(classInfoId));
            if (CollectionUtils.isEmpty(classStuRealationVoList)) {
                return new PageData<StuInfoVO>(Collections.EMPTY_LIST, 0);
            }
            List<Long> collect = classStuRealationVoList.stream().map(e -> e.getStudentId()).distinct().collect(Collectors.toList());
            stuInfoVoList = stuInfoVoList.stream().filter(e -> collect.contains(e.getStudentId())).collect(Collectors.toList());
        }

        String studentName = (String)params.get("studentName");
        List<SysUserDTO> userDtoList = sysUserService.getAll();
        if (StringUtils.isNotBlank(studentName)) {
            List<SysUserDTO> sysUserDtoList = userDtoList.stream().filter(e -> e.getRealName().contains(studentName)).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(sysUserDtoList)) {
                return new PageData<StuInfoVO>(Collections.EMPTY_LIST, 0);
            }
            List<Long> collect = sysUserDtoList.stream().map(e -> e.getId()).distinct().collect(Collectors.toList());
            stuInfoVoList = stuInfoVoList.stream().filter(e -> collect.contains(e.getStudentId())).collect(Collectors.toList());
        }
        int size = stuInfoVoList.size();

        Integer page = Integer.valueOf((String) params.get("page"));
        Integer limit = Integer.valueOf((String) params.get("limit"));
        List<StuInfoVO> pageList = stuInfoVoList.stream().skip((page - 1) * limit).limit(limit).collect(Collectors.toList());

        pageList.forEach(e -> {
            SysUserDTO student = userDtoList.stream().filter(j -> j.getId().compareTo(e.getStudentId()) == 0).findAny().orElse(null);
            e.setStudentName(student == null ? "-" : student.getRealName());
            e.setHeadUrl(student == null ? "-" : student.getHeadUrl());

            ClassStuRealationVO classStuRealationVo = classStuRealationService.queryByStudentId(e.getStudentId());
            if (classStuRealationVo != null) {
                ClassInfoVO classInfoVo = classInfoService.get(classStuRealationVo.getClassInfoId());
                if (classInfoVo != null) {
                    e.setClassName(classInfoVo.getClassName());

                    SysUserDTO teacher = userDtoList.stream().filter(j -> j.getId().compareTo(classInfoVo.getTeacherId()) == 0).findAny().orElse(null);
                    e.setTeacherName(teacher.getRealName());
                } else {
                    e.setClassName("-");
                    e.setTeacherName("-");
                }
            }
        });
        return new PageData<StuInfoVO>(pageList, size);
    }

    @Override
    public StuInfoVO getByStudentId(Long studentId) {
        QueryWrapper<StuInfoEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("student_id", studentId);
        StuInfoEntity stuInfoEntity = this.baseDao.selectOne(wrapper);
        return ConvertUtils.sourceToTarget(stuInfoEntity, StuInfoVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveStuinfo(StuInfoDTO dto) {
        ClassStuRealationVO classStuRealationVo = classStuRealationService.queryByStudentId(dto.getStudentId());
        if (classStuRealationVo != null) {
            throw new RenException("该学生已绑定班级！请勿重复绑定！");
        }
        classStuRealationService.save(ConvertUtils.sourceToTarget(dto, ClassStuRealationDTO.class));
        this.save(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStuinfo(StuInfoDTO dto) {
        ClassStuRealationVO classStuRealationVo = classStuRealationService.queryByStudentId(dto.getStudentId());
        ClassStuRealationDTO classStuRealationDto = ConvertUtils.sourceToTarget(dto, ClassStuRealationDTO.class);
        classStuRealationDto.setId(classStuRealationVo.getId());
        classStuRealationService.update(classStuRealationDto);
        this.update(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteStuinfo(Long[] ids) {
        List<StuInfoEntity> stuInfoEntityList = this.baseDao.selectBatchIds(Arrays.asList(ids));
        stuInfoEntityList.forEach(e -> {
            classStuRealationService.deleteByStudentId(e.getStudentId());
            this.baseDao.deleteById(e.getId());
        });
    }

    @Override
    public List<StuInfoVO> exportList(Map<String, Object> params) {
        String classInfoId = (String)params.get("classInfoId");
        if (StringUtils.isNotBlank(classInfoId)) {
            List<ClassStuRealationVO> classStuRealationVoList = classStuRealationService.queryByClassInfoId(Long.valueOf(classInfoId));
            if (CollectionUtils.isEmpty(classStuRealationVoList)) {
                return Collections.EMPTY_LIST;
            }
            params.put("studentIdList", classStuRealationVoList.stream().map(e -> e.getStudentId().toString()).distinct().collect(Collectors.joining(",")));
        }

        List<SysUserDTO> userDtoList = sysUserService.getAll();
        String studentName = (String)params.get("studentName");
        if (StringUtils.isNotBlank(studentName)) {
            List<SysUserDTO> sysUserDtoList = userDtoList.stream().filter(e -> e.getRealName().contains(studentName)).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(sysUserDtoList)) {
                return Collections.EMPTY_LIST;
            }
            params.put("studentIdList", sysUserDtoList.stream().map(e -> e.getId().toString()).distinct().collect(Collectors.joining(",")));
        }

        Long userId = SecurityUser.getUserId();
        SysRoleDTO studentRole = sysRoleService.getRole("student");
        List<Long> userIdList = sysRoleUserService.getUserIdList(studentRole.getId());
        if (CollectionUtils.isNotEmpty(userIdList) && userIdList.contains(userId)) {
            ClassStuRealationVO classStuRealationVo = classStuRealationService.queryByStudentId(userId);
            if (classStuRealationVo == null) {
                throw new RenException("您还未绑定班级！无法查看班级信息！");
            }
            List<ClassStuRealationVO> classStuRealationVoList = classStuRealationService.queryByClassInfoId(classStuRealationVo.getClassInfoId());
            params.put("studentIdList", classStuRealationVoList.stream().map(e -> e.getStudentId().toString()).distinct().collect(Collectors.joining(",")));
        }
        List<StuInfoVO> stuInfoVoList = this.list(params);
        stuInfoVoList.forEach(e -> {
            SysUserDTO student = userDtoList.stream().filter(j -> j.getId().compareTo(e.getStudentId()) == 0).findAny().orElse(null);
            e.setStudentNumber(student == null ? "-" : student.getUsername());
            e.setStudentName(student == null ? "-" : student.getRealName());
            e.setHeadUrl(student == null ? "-" : student.getHeadUrl());

            ClassStuRealationVO classStuRealationVo = classStuRealationService.queryByStudentId(e.getStudentId());
            if (classStuRealationVo != null) {
                ClassInfoVO classInfoVo = classInfoService.get(classStuRealationVo.getClassInfoId());
                if (classInfoVo != null) {
                    e.setClassName(classInfoVo.getClassName());

                    SysUserDTO teacher = userDtoList.stream().filter(j -> j.getId().compareTo(classInfoVo.getTeacherId()) == 0).findAny().orElse(null);
                    e.setTeacherName(teacher.getRealName());
                } else {
                    e.setClassName("-");
                    e.setTeacherName("-");
                }
            }
        });
        return stuInfoVoList;
    }


}